home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 April: Mac OS SDK / Dev.CD Apr 97 SDK1.toast / Development Kits (Disc 1) / Apple Shared Library Manager / ASLM Examples / TestTools / Sources / TestStandardPool.cp < prev    next >
Encoding:
Text File  |  1996-11-19  |  11.0 KB  |  496 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        TestStandardPool.cp
  3.  
  4.     Contains:    Methods for TTestStandardPool
  5.  
  6.     Copyright:    © 1992-1995 by Apple Computer, Inc., all rights reserved.
  7.  
  8. */
  9.  
  10. #ifndef __GLOBALNEW__
  11. #include <GlobalNew.h>
  12. #endif
  13. #ifndef __TESTSTANDARDPOOL__
  14. #include "TestStandardPool.h"
  15. #endif
  16. #ifndef __MIXEDMODE__
  17. #include <MixedMode.h>
  18. #endif
  19.  
  20. size_t StringToNum(char* str);
  21. size_t RandomNumber(size_t lo, size_t hi);
  22.  
  23. /*******************************************************************************
  24. ** CLASS Declaration
  25. ********************************************************************************/
  26.  
  27. class TMyPoolNotifier : public TPoolNotifier
  28. {
  29.     public:
  30.                             TMyPoolNotifier(void* memory);
  31.         virtual                ~_CDECL TMyPoolNotifier();
  32.         
  33.         virtual void        _CDECL Notify(EventCode, OSErrParm, void*);
  34.         
  35.     private:
  36.         void*    fMemory;
  37. };
  38.  
  39. TMyPoolNotifier::TMyPoolNotifier(void* memory)
  40. {
  41.     fMemory = memory;
  42. }
  43.  
  44. TMyPoolNotifier::~TMyPoolNotifier()
  45. {}
  46.  
  47. void TMyPoolNotifier::Notify(EventCode code, OSErrParm err, void*)
  48. {
  49.     if (code == kLowPoolMemoryEvent && err == kNoError)
  50.     {
  51.         if (fMemory)
  52.         {
  53.             TMemoryPool::FreeMemory(fMemory);
  54.             fMemory = NULL;
  55.         }
  56.     }
  57. }
  58. /**********************************************************************
  59. ** External "C" Declarations
  60. ***********************************************************************/
  61.  
  62. extern "C"
  63. {
  64. #if GENERATINGPOWERPC
  65.     
  66.     struct CLI {
  67.         short fWord[6];
  68.     } gcli68K = {
  69.             0x40c0,                        /* move  SR,D0        */
  70.             0x007C, 0x0700,                /* ori.w #$0700,SR    */
  71.             0x027C, 0xFEFF,                /* andi.w #$FEFF,SR    */
  72.             0x4e75
  73.     };
  74.     
  75.     struct STI {
  76.         short fWord[2];
  77.     } gsti68K = {
  78.             0x46c0,                        /* move.w D0,SR        */
  79.             0x4e75
  80.     };
  81.     
  82.     #define pcli() CallUniversalProc((UniversalProcPtr)&gcli68K, kRegisterBased | REGISTER_RESULT_LOCATION(kRegisterD0) | RESULT_SIZE(kTwoByteCode))
  83.     #define psti(save) CallUniversalProc((UniversalProcPtr)&gsti68K, kRegisterBased | REGISTER_ROUTINE_PARAMETER(1, kRegisterD0, kTwoByteCode), save)
  84.  
  85. #else
  86.  
  87.     short pcli() = 
  88.     {
  89.         0x40c0,                        /* move  SR,D0        */
  90.         0x007C, 0x0700,                /* ori.w #$0700,SR    */
  91.         0x027C, 0xFEFF                /* andi.w #$FEFF,SR    */
  92.     };
  93.     #pragma parameter psti(__D0)
  94.     void psti(short) = 
  95.     {
  96.         0x46c0                        /* move.w D0,SR        */
  97.     };
  98.  
  99. #endif
  100. };
  101.  
  102. /*******************************************************************************
  103. ** Some Constants
  104. ********************************************************************************/
  105.  
  106. const size_t    kNumPoolOps        = 5;
  107. const size_t    kNumMemory        = 25;
  108. const size_t    kMaxMemSize        = 255;
  109.  
  110. #define kDontTouch    ((char*)-1L)
  111.  
  112. /*******************************************************************************
  113. ** TPoolTestOperation
  114. ********************************************************************************/
  115.  
  116. TPoolTestOperation::TPoolTestOperation(char** array, size_t size, size_t small,
  117.                                        size_t large)
  118. {
  119.     fArray        = array;
  120.     fArraySize    = size;
  121.     fFinished    = true;
  122.     fSmallest    = small;
  123.     fLargest    = large;
  124.     fAllocs        = 0;
  125.     fDeletes    = 0;
  126. }
  127.  
  128. TPoolTestOperation::~TPoolTestOperation()
  129. {}
  130.  
  131. void TPoolTestOperation::Process()
  132. {
  133.     size_t toAlloc = RandomNumber(0, fArraySize);
  134.     size_t count = 0;
  135.  
  136.     for (count = 0; count < toAlloc; ++count)
  137.     {
  138.         size_t which = RandomNumber(0, fArraySize - 1);
  139.         if (fArray[which] == NULL)
  140.         {
  141.             char* temp = new char[RandomNumber(fSmallest, fLargest)];
  142.             fAllocs += 1;
  143.             short save;
  144.             save = pcli();
  145.             if (fArray[which] == NULL)
  146.             {
  147.                 fArray[which] = temp;
  148.                 psti(save);
  149.             }
  150.             else
  151.             {
  152.                 psti(save);
  153.                 delete temp;
  154.                 fDeletes += 1;
  155.             }
  156.         }
  157.     }
  158.     size_t toFree = RandomNumber(0, fArraySize);
  159.     for (count = 0; count < toFree; ++count)
  160.     {
  161.         size_t which = RandomNumber(0, fArraySize - 1);
  162.         short save;
  163.         save = pcli();
  164.         if (fArray[which] != NULL && fArray[which] != kDontTouch)
  165.         {
  166.             char* temp = fArray[which];
  167.             fArray[which] = NULL;
  168.             psti(save);
  169.             delete temp;
  170.             fDeletes += 1;
  171.         }
  172.         else
  173.             psti(save);
  174.     }
  175.     fFinished = true;
  176. }
  177.  
  178. /*******************************************************************************
  179. ** PUBLIC Constructor/Destructor
  180. ********************************************************************************/
  181.  
  182. Constructor(StandardPool)
  183. Destructor(StandardPool)
  184.  
  185. /*******************************************************************************
  186. ** PUBLIC InitTest
  187. ********************************************************************************/
  188.  
  189. void TTestStandardPool :: InitTest(BooleanParm verbose, BooleanParm, int argc, char** argv)
  190. {
  191.     TStandardPool* pool = GetPool();
  192.         
  193.     if (pool == NULL)
  194.     {
  195.         Printf("### ERROR: There is no global pool\n");
  196.         return;
  197.     }
  198.         
  199.     SetLocalPool(pool);
  200.     
  201.     fSmallest    = 1;
  202.     fLargest    = 255;
  203.     fAllocs        = 0;
  204.     fDeletes    = 0;
  205.     fReallocs    = 0;
  206.     fIterations = 5000;
  207.     size_t    idx = 0;
  208.     while (argc)
  209.     {
  210.         char*    str;
  211.         
  212.         str = argv[idx];
  213.         if (*str != '-')
  214.             break;
  215.         argc -= 1;
  216.         idx += 1;
  217.         switch (str[1])
  218.         {
  219.             case 'i':
  220.             case 'I':
  221.                 fIterations = StringToNum(argv[idx++]);
  222.                 argc -= 1;
  223.                 break;
  224.                 
  225.             default: 
  226.                 argc = 0;
  227.                 Printf("WARNING: Option at and after '%s' not understood!\n", str);
  228.                 break;
  229.         }
  230.  
  231.     }
  232.     fSmallest     = 1;
  233.     fLargest    = 255;
  234.     if (argc)
  235.     {
  236.         if (argc == 1)
  237.             Printf("WARNING: Option '%s' not understood!\n", argv[idx]);
  238.         else
  239.         if (argc != 2)
  240.             Printf("WARNING: Options at and after '%s' not understood!\n",
  241.                    argv[idx]);
  242.         else
  243.         {
  244.             fSmallest = StringToNum(argv[idx++]);
  245.             fLargest = StringToNum(argv[idx++]);
  246.             if (verbose)
  247.                 Printf("INFO: Smallest size = %u\nINFO: Largest size = %u\n",
  248.                        fSmallest, fLargest);
  249.         }
  250.     }
  251. }
  252.  
  253.  
  254. /**********************************************************************
  255. ** PUBLIC RunTestIteration
  256. ***********************************************************************/
  257.  
  258. void TTestStandardPool :: RunTestIteration(BooleanParm verbose, BooleanParm)
  259. {
  260.     TPoolTestOperation*    ops[kNumPoolOps];
  261.     TTimeScheduler*        sched = new TTimeScheduler;
  262.     char*                memory[kNumMemory];
  263.     size_t                idx, jdx;
  264.     TStopwatch            stamp;
  265.  
  266.     //
  267.     // First, we do some quick tests on the pool
  268.     //
  269.     {
  270.         if (verbose)
  271.             Printf("### INFO: Testing Pool Notifiers\n");
  272.         TStandardPool* pool = new (2500, kCurrentZone, kNormalMemory) TStandardPool;
  273.         if (pool)
  274.         {
  275.             void* memory = pool->Allocate(2000);
  276.             if (memory == NULL)
  277.             {
  278.                 Printf("### ERROR: Couldn't allocate 2000 bytes from a 2500 byte pool\n");
  279.             }
  280.             else
  281.             {
  282.                 Boolean ok = true;
  283.                 void* mem2 = pool->Allocate(2000);
  284.                 if (mem2)
  285.                 {
  286.                     Printf("### ERROR: Allocated 4000 bytes from a 2500 byte pool\n");
  287.                     ok = false;
  288.                     pool->Free(mem2);
  289.                 }
  290.                 else
  291.                 {
  292.                     TMyPoolNotifier    notifier(memory);
  293.                     pool->SetNotifier(¬ifier);
  294.                     mem2 = pool->Allocate(2000);
  295.                     if (mem2 == NULL)
  296.                     {
  297.                         ok = false;
  298.                         Printf("### ERROR: Couldn't allocate 2000 bytes using the notifier\n");
  299.                     }
  300.                     void* mem3 = pool->Allocate(2000);
  301.                     if (mem3 == NULL)
  302.                     {
  303.                         Printf("### ERROR: Pool didn't grow\n");
  304.                         ok = false;
  305.                     }
  306.                     else
  307.                         pool->Free(mem3);
  308.                     if (mem2)
  309.                         pool->Free(mem2);
  310.                     pool->SetNotifier(NULL);
  311.                     if (verbose && ok)
  312.                         Printf("### INFO: Pool notifiers seemed to work!\n");
  313.                 }
  314.             }
  315.             delete pool;
  316.         }
  317.         else
  318.             Printf("### ERROR: Couldn't create a 2500 byte pool\n");
  319.     }
  320.         
  321.     memset(memory, 0, sizeof(memory));
  322.     
  323.     for (idx = 0; idx < kNumPoolOps; ++idx)
  324.         ops[idx] = new TPoolTestOperation(memory, kNumMemory, fSmallest, fLargest);
  325.     
  326.     (&stamp)->Reset();
  327.     
  328.     Printf("       0: ");
  329.     for (idx = 0; idx < fIterations; ++idx)
  330.     {
  331.         if ((idx + 1) % 100 == 0)
  332.             Printf(".");
  333.         if ((idx + 1) % 2500 == 0)
  334.             Printf("\n%8u: ", idx + 1);
  335.         //
  336.         // Schedule any operations that are not scheduled
  337.         //
  338.         for (jdx = 0; jdx < kNumPoolOps; ++jdx)
  339.             if (ops[jdx]->fFinished)
  340.             {
  341.                 ops[jdx]->fFinished = false;
  342.                 ops[jdx]->SetTime(jdx + 1);
  343.                 sched->Schedule(ops[jdx]);
  344.             }
  345.         
  346.         size_t toAlloc = RandomNumber(0, kNumMemory);
  347.         size_t count = 0;
  348.         for (count = 0; count < toAlloc; ++count)
  349.         {
  350.             size_t which = RandomNumber(0, kNumMemory - 1);
  351.             if (memory[which] == NULL)
  352.             {
  353.                 size_t size = RandomNumber(fSmallest, fLargest);
  354.                 char* temp = new char[size];
  355.                 fAllocs += 1;
  356.                 short save;
  357.                 save = pcli();
  358.                 if (memory[which] == NULL)
  359.                 {
  360.                     memory[which] = temp;
  361.                     psti(save);
  362.                 }
  363.                 else
  364.                 {
  365.                     psti(save);
  366.                     delete temp;
  367.                     fDeletes += 1;
  368.                 }
  369.             }
  370.         }
  371.         //
  372.         // Schedule any operations that are not scheduled
  373.         //
  374.         for (jdx = 0; jdx < kNumPoolOps; ++jdx)
  375.             if (ops[jdx]->fFinished)
  376.             {
  377.                 ops[jdx]->fFinished = false;
  378.                 ops[jdx]->SetTime(jdx + 1);
  379.                 sched->Schedule(ops[jdx]);
  380.             }
  381.             
  382.         size_t toFree = RandomNumber(0, kNumMemory);
  383.         for (count = 0; count < toFree; ++count)
  384.         {            
  385.             size_t which = RandomNumber(0, kNumMemory - 1);
  386.             short save;
  387.             save = pcli();
  388.             if (memory[which] != NULL && memory[which] != kDontTouch)
  389.             {
  390.                 char* temp = memory[which];
  391.                 memory[which] = NULL;
  392.                 psti(save);
  393.                 delete temp;
  394.                 fDeletes += 1;
  395.             }
  396.             else
  397.                 psti(save);
  398.         }
  399.         //
  400.         // Schedule any operations that are not scheduled
  401.         //
  402.         for (jdx = 0; jdx < kNumPoolOps; ++jdx)
  403.             if (ops[jdx]->fFinished)
  404.             {
  405.                 ops[jdx]->fFinished = false;
  406.                 ops[jdx]->SetTime(jdx + 1);
  407.                 sched->Schedule(ops[jdx]);
  408.             }
  409.  
  410.         size_t toResize = RandomNumber(0, kNumMemory);
  411.         for (count = 0; count < toResize; ++count)
  412.         {            
  413.             size_t which = RandomNumber(0, kNumMemory - 1);
  414.             size_t newSize = RandomNumber(fSmallest, fLargest);
  415.             short save;
  416.             save = pcli();
  417.             if (memory[which] != NULL && memory[which] != kDontTouch)
  418.             {
  419.                 char* temp = memory[which];
  420.                 memory[which] = kDontTouch;
  421.                 psti(save);
  422.                 char* temp1 = (char*)TMemoryPool::ReallocateMemory(temp, newSize);
  423.                 fReallocs += 1;
  424.                 save = pcli();
  425.                 memory[which] = temp1;
  426.                 psti(save);
  427.                 if (temp1 == NULL)
  428.                 {
  429.                     fDeletes += 1;
  430.                     delete temp;
  431.                 }
  432.             }
  433.             else
  434.                 psti(save);
  435.         }
  436.         //
  437.         // Schedule any operations that are not scheduled
  438.         //
  439.         for (jdx = 0; jdx < kNumPoolOps; ++jdx)
  440.             if (ops[jdx]->fFinished)
  441.             {
  442.                 ops[jdx]->fFinished = false;
  443.                 ops[jdx]->SetTime(jdx + 1);
  444.                 sched->Schedule(ops[jdx]);
  445.             }
  446.  
  447.         if (!GetDefaultPool()->CheckPool())
  448.         {
  449.             Printf("\nERROR: CheckPool() Failed ... ABORTING TEST\n");
  450.             break;
  451.         }
  452.     }
  453.     for (jdx = 0; jdx < kNumPoolOps; ++jdx)
  454.         if (!ops[jdx]->fFinished)
  455.             jdx = 0;
  456.             
  457.     unsigned long seconds = (&stamp)->ElapsedSeconds();
  458.     unsigned long allocs, frees, reallocs;
  459.     allocs = fAllocs;
  460.     frees = fDeletes;
  461.     reallocs = fReallocs;
  462.     if (seconds == 0)
  463.         seconds = 1;
  464.     for (jdx = 0; jdx < kNumPoolOps; ++jdx)
  465.     {
  466.         allocs += ops[jdx]->fAllocs;
  467.         frees += ops[jdx]->fDeletes;
  468.     }
  469.     
  470.     delete sched;
  471.     for (jdx = 0; jdx < kNumPoolOps; ++jdx)
  472.     {
  473.         TPoolTestOperation* op = ops[jdx];
  474.         delete op;
  475.     }
  476.     for (jdx = 0; jdx < kNumMemory; ++jdx)
  477.         delete memory[jdx];
  478.         
  479.     if (verbose)
  480.     {
  481.         Printf("\n\nINFO: # Allocates   = %8u   per second = %4u\n", allocs, allocs/seconds);
  482.         Printf("INFO: # Deletes     = %8u   per second = %4u\n", frees, frees/seconds);
  483.         Printf("INFO: # Reallocates = %8u   per second = %4u\n\n", reallocs, reallocs/seconds);
  484.     }        
  485. }
  486.  
  487. /**********************************************************************
  488. ** PUBLIC EndTest
  489. ***********************************************************************/
  490.  
  491. void TTestStandardPool :: EndTest(BooleanParm verbose, BooleanParm)
  492. {
  493.     if (verbose)
  494.         Printf("INFO: End of StandardPool test\n");
  495. }
  496.